//! Actix web Diesel integration example
//!
//! Diesel does not support tokio, so we have to run it in separate threads using the web::block
//! function which offloads blocking code (like Diesel's) in order to not block the server's thread.



use actix_web::{ middleware,   App,   HttpServer};
use diesel::prelude::*;
use diesel::r2d2::{self, ConnectionManager};
use dotenv::dotenv;
use actix_files as fs;

// mod actions;
// mod models;
// mod schema;
use crate::todo;
use crate::user;

// type DbPool = r2d2::Pool<ConnectionManager<SqliteConnection>>;


#[actix_web::main]
pub async fn main() -> std::io::Result<()> {
    std::env::set_var("RUST_LOG", "actix_web=info");
    env_logger::init();
    dotenv().ok();

    // set up database connection pool
    let connspec = std::env::var("DATABASE_URL").expect("DATABASE_URL");
    println!("{}",connspec);
    let manager = ConnectionManager::<SqliteConnection>::new(connspec);
    let pool = r2d2::Pool::builder()
        .build(manager)
        .expect("Failed to create pool.");

    let bind = "127.0.0.1:8000";

    println!("Starting server at: {}", &bind);

    // Start HTTP server
    HttpServer::new(move || {
        App::new()
            // set up DB pool to be used with web::Data<Pool> extractor
            .data(pool.clone())
            .wrap(middleware::Logger::default())
            .configure(user::init) // init user routes
            .configure(todo::init) // init user routes
            .service(fs::Files::new("/static", "./static").show_files_listing())
    }).workers(1)
    .bind(&bind)?
    .run()
    .await
}

// #[cfg(test)]
// mod tests {
//     use super::*;
//     use actix_web::test;

//     #[actix_rt::test]
//     async fn user_routes() {
//         std::env::set_var("RUST_LOG", "actix_web=debug");
//         env_logger::init();
//         dotenv::dotenv().ok();

//         let connspec = std::env::var("DATABASE_URL").expect("DATABASE_URL");
//         let manager = ConnectionManager::<SqliteConnection>::new(connspec);
//         let pool = r2d2::Pool::builder()
//             .build(manager)
//             .expect("Failed to create pool.");

//         let mut app = test::init_service(
//             App::new()
//                 .data(pool.clone())
//                 .wrap(middleware::Logger::default())
//                 .configure(todo::init)
//                 .service(get_user)
//                 .service(add_user),
//         )
//         .await;

//         // Insert a user
//         let req = test::TestRequest::post()
//             .uri("/user")
//             .set_json(&models::NewUser {
//                 name: "Test user".to_owned(),
//             })
//             .to_request();

//         let resp: models::User = test::read_response_json(&mut app, req).await;

//         assert_eq!(resp.name, "Test user");

//         // Get a user
//         let req = test::TestRequest::get()
//             .uri(&format!("/user/{}", resp.id))
//             .to_request();

//         let resp: models::User = test::read_response_json(&mut app, req).await;

//         assert_eq!(resp.name, "Test user");

//         // Delete new user from table
//         use crate::schema::users::dsl::*;
//         diesel::delete(users.filter(id.eq(resp.id)))
//             .execute(&pool.get().expect("couldn't get db connection from pool"))
//             .expect("couldn't delete test user from table");
//     }
// }
